/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
package fr.jade.fraclite.adl.attributes;

import java.util.Map;

import org.objectweb.fractal.adl.ADLException;
import org.objectweb.fractal.adl.AbstractLoader;
import org.objectweb.fractal.adl.Definition;
import org.objectweb.fractal.adl.Node;
import org.objectweb.fractal.adl.attributes.Attribute;
import org.objectweb.fractal.adl.attributes.Attributes;
import org.objectweb.fractal.adl.attributes.AttributesContainer;
import org.objectweb.fractal.adl.components.Component;
import org.objectweb.fractal.adl.components.ComponentContainer;
import org.objectweb.fractal.adl.components.ComponentDefinition;


/**
 * A {@link org.objectweb.fractal.adl.Loader} to check {@link Attributes} nodes 
 * in definitions. This loader replace the standard loader to provide a support 
 * for generic attribute controller.
 * @author nono
 * @contact noel.depalma@inrialpes.fr
 */

public class GenericAttributeLoader extends AbstractLoader {
  
  // --------------------------------------------------------------------------
  // Implementation of the Loader interface
  // --------------------------------------------------------------------------
  
  @SuppressWarnings("unchecked")
  public Definition load (final String name, final Map context) throws ADLException {
    Definition d = clientLoader.load(name, context);
    boolean extend = false;
    if (d instanceof ComponentDefinition) {
      extend = ((ComponentDefinition)d).getExtends() != null;
    }
    checkNode(d, extend);
    return d;
  }

  // --------------------------------------------------------------------------
  // Checking methods
  // --------------------------------------------------------------------------
  
  private void checkNode (final Object node, final boolean extend) 
    throws ADLException 
  {
    if (node instanceof AttributesContainer) {
      checkAttributesContainer((AttributesContainer)node, extend);
    }
    if (node instanceof ComponentContainer) {
      Component[] comps = ((ComponentContainer)node).getComponents();
      for (int i = 0; i < comps.length; i++) {
        checkNode(comps[i], extend);
      }
    }
  }

  private void checkAttributesContainer (
    final AttributesContainer container,
    final boolean extend) throws ADLException
  {
    Attributes attrs = container.getAttributes();
    if (attrs != null) {
      String signature = attrs.getSignature();
      if (signature == null) {
        if (!extend) {
          throw new ADLException("Signature missing", (Node)attrs);
        } else {
          return;
        }
      }
      ClassLoader cl = getClass().getClassLoader();
      try {
          cl.loadClass(signature);
      } catch (ClassNotFoundException e) {
        throw new ADLException(
          "Invalid signature '" + signature + "'", (Node)attrs, e);
      }

      Attribute[] attributes = attrs.getAttributes();
      for (int i = 0; i < attributes.length; ++i) {
        String attrName = attributes[i].getName();
        String attrValue = attributes[i].getValue();
        if (attrName == null) {
          throw new ADLException("Attribute name missing", (Node)attributes[i]);
        }
        if (attrValue == null) {
          throw new ADLException("Attribute value missing", (Node)attributes[i]);
        }
      }
    }
  }
}
